package 链表;

/**
 * @ClassName : _794_有效的井字游戏
 * @Author : 骆发茂
 * @Date: 2021/12/9 16:17
 * @Description : https://leetcode-cn.com/problems/valid-tic-tac-toe-state/
 * 分情况讨论
 * 【宫水三叶】分情况讨论模拟题
 * 给定的棋盘大小固定，对于无效情况进行分情况讨论即可：
 * X是先先手于O的
 * 1、X必须比O多1个或者相同，否则false； 2、X和O不能同时都是赢家，否则false；
 * 3、X赢的时候必须比O多1个，否则false； 4、O赢得时候个数与X相同，否则false；
 * 由于 X 先手，O 后手，两者轮流下子。因此 O 的数量不会超过 X，且两者数量差不会超过 1，否则为无效局面；
 * 若局面是 X 获胜，导致该局面的最后一个子必然是 X，此时必然有 X 数量     大于 O（X 为先手），（同时成立才行）否则为无效局面；
 * 若局面是 O 获胜，导致该局面的最后一个子必然是 O，此时必然有 X 数量     等于 O（X 为先手），（同时成立才行）否则为无效局面；
 * 局面中不可能出现两者同时赢（其中一方赢后，游戏结束）。
 *
 */
public class _794_有效的井字游戏_from宫水三叶 {
//    public static void main(String[] args) {
//        System.out.println(validTicTacToe(new String[]{"XO ","XO ","XO "}));
//    }
    class Solution {
        public boolean validTicTacToe(String[] board) {
            char[][] cs = new char[3][3];
            int Xcount = 0, Ocount = 0;
            //获取里面所有的Xcount，Ocount
            for (int i = 0; i < 3; i++) {
                for (int j = 0; j < 3; j++) {
                    char c = board[i].charAt(j);
                    if (c == 'X') Xcount++;
                    else if (c == 'O') Ocount++;
                    //填充二维数组
                    cs[i][j] = c;
                }
            }
            boolean a = check(cs, 'X'), b = check(cs, 'O');
            // * 由于 X 先手，O 后手，两者轮流下子。因此 O 的数量不会超过 X，且两者数量差不会超过 11，否则为无效局面；
            if (Ocount > Xcount || Xcount - Ocount > 1) return false;
            // * 若局面是 X 获胜，导致该局面的最后一个子必然是 X，此时必然有 X 数量大于 O（X 为先手），否则为无效局面；
            if (a && Xcount <= Ocount) return false;
            // * 若局面是 O 获胜，导致该局面的最后一个子必然是 O，此时必然有 X 数量等于 O（X 为先手），否则为无效局面；
            if (b && Ocount != Xcount) return false;
            if (a && b) return false;
            return true;
        }
        boolean check(char[][] cs, char c) {
            for (int i = 0; i < 3; i++) {
                //横向3连
                if (cs[i][0] == c && cs[i][1] == c && cs[i][2] == c)
                    return true;//   行位不变、列位在变化，横线123
                //纵向3连
                if (cs[0][i] == c && cs[1][i] == c && cs[2][i] == c)
                    return true;//   列位不变、行位在变化，竖线123
            }
            boolean a = true, b = true;
            for (int i = 0; i < 3; i++) {
                for (int j = 0; j < 3; j++) {
                    //11，22，33，=x,或者=o
                    if (i == j) a &= cs[i][j] == c;//            \斜线
                    if (i + j == 2) b &= cs[i][j] == c;//        /斜线
                }
            }
            return a || b;
        }
    }

}